package fun.ipconfig.shopping.configure.context;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.log.LogMessage;
import org.springframework.security.core.context.DeferredSecurityContext;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.context.HttpRequestResponseHolder;
import org.springframework.security.web.context.SecurityContextRepository;

import java.util.function.Supplier;

/**
 * 自定义上下文管理
 * @author gtl
 */
public class DefaultSecurityContext implements SecurityContextRepository {
    Logger logger = LoggerFactory.getLogger(DefaultSecurityContext.class);


    @Override
    public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) { return null; }

    @Override
    public DeferredSecurityContext loadDeferredContext(HttpServletRequest request) {
        SecurityContext context = null; 
        Supplier<SecurityContext> supplier = () -> context;
        logger.info("获取: {}", context);
        return  new NextContext(supplier, SecurityContextHolder.getContextHolderStrategy());
    }

    @Override
    public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) {
        String sessionId = ((WebAuthenticationDetails)context.getAuthentication().getDetails()).getSessionId();
        sessionId = sessionId == null ? response.getHeader("Set-Cookie").split(";")[0].split("=")[1] : sessionId;
        logger.info("登录: sessionId {} 用户 {}",sessionId, context.getAuthentication().getPrincipal());
    }

    @Override
    public boolean containsContext(HttpServletRequest request) {
        return false;
    }

    final class NextContext implements DeferredSecurityContext {

        private static final Log logger = LogFactory.getLog(NextContext.class);

        private final Supplier<SecurityContext> supplier;

        private final SecurityContextHolderStrategy strategy;

        private SecurityContext securityContext;

        private boolean missingContext;

        NextContext(Supplier<SecurityContext> supplier, SecurityContextHolderStrategy strategy) {
            this.supplier = supplier;
            this.strategy = strategy;
        }

        @Override
        public SecurityContext get() {
            init();
            return this.securityContext;
        }

        @Override
        public boolean isGenerated() {
            init();
            return this.missingContext;
        }

        private void init() {
            if (this.securityContext != null) {
                return;
            }

            this.securityContext = this.supplier.get();
            this.missingContext = (this.securityContext == null);
            if (this.missingContext) {
                this.securityContext = this.strategy.createEmptyContext();
                if (logger.isTraceEnabled()) {
                    logger.trace(LogMessage.format("Created %s", this.securityContext));
                }
            }
        }
    }
}
